package com.wsd.jing.handler;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
import com.wsd.jing.annotation.DataPermission;
import com.wsd.jing.entity.RolePermission;
import com.wsd.jing.entity.User;
import com.wsd.jing.enums.DataEnum;
import com.wsd.jing.mapper.UserMapper;
import com.wsd.jing.service.IDepartmentService;
import com.wsd.jing.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.HexValue;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.schema.Column;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * All rights Reserved, Designed By www.tom.com
 *
 * @author tom
 * @version 1.0.0
 * @projectName: jing
 * @packageName: com.wsd.jing.handler
 * @className: DataPermissionHandler
 * @description 数据权限handler
 * @createDate 2022/12/23 13:09
 * @copyright 2022/12/23 13:09 www.tom.com Inc. All rights reserved.
 */
@Slf4j
public class CustomDataPermissionHandler implements DataPermissionHandler {

    @Override
    public Expression getSqlSegment(Expression where, String mappedStatementId) {
        try {
            Class<?> mapperClass = Class.forName(mappedStatementId.substring(0, mappedStatementId.lastIndexOf(".")));
            Method[] methods = mapperClass.getDeclaredMethods();
            for (Method method : methods) {
                DataPermission mapperClassAnnotation = method.getAnnotation(DataPermission.class);
                if (ObjectUtil.isNotEmpty(mapperClassAnnotation) && mapperClassAnnotation.enabled()) {
                    IUserService userService = SpringUtil.getBean(IUserService.class);
                    RolePermission rolePermission = userService.getUserRolePermission(StpUtil.getLoginIdAsInt());

                    if (ObjectUtil.isEmpty(rolePermission)) {
                        log.error("获取当前用户权限数据为空！");
                        return where;
                    }

                    Expression expression = new HexValue(" 1 = 1 ");
                    if (where == null) {
                        where = expression;
                    }

                    String tableAlias = mapperClassAnnotation.tableAlias();
                    String departmentFiled = StrUtil.isEmpty(tableAlias) ? mapperClassAnnotation.departmentFiled() : tableAlias + "." + mapperClassAnnotation.departmentFiled();
                    String creatorFiled = StrUtil.isEmpty(tableAlias) ? mapperClassAnnotation.creatorFiled() : tableAlias + "." + mapperClassAnnotation.creatorFiled();
                    Integer type = rolePermission.getType();
                    DataEnum dataEnum = DataEnum.getValue(type);
                    switch (dataEnum) {
                        case ALL:
                            return where;
                        case DEPARTMENT:
                            User user = SpringUtil.getBean(UserMapper.class).selectById(StpUtil.getLoginIdAsInt());
                            EqualsTo departmentEqualsTo = new EqualsTo();
                            departmentEqualsTo.setLeftExpression(new Column(departmentFiled));
                            departmentEqualsTo.setRightExpression(new LongValue(user.getDepartmentId()));
                            return new AndExpression(where, departmentEqualsTo);
                        case DEPARTMENT_ALL:
                            User user1 = SpringUtil.getBean(UserMapper.class).selectById(StpUtil.getLoginIdAsInt());
                            Set<String> departmentAllSet = SpringUtil.getBean(IDepartmentService.class).listTreeDepartmentIds(user1.getDepartmentId());
                            ItemsList departmentAllItemsList = new ExpressionList(departmentAllSet.stream().map(LongValue::new).collect(Collectors.toList()));
                            InExpression departmentInExpression = new InExpression(new Column(departmentFiled), departmentAllItemsList);
                            return new AndExpression(where, departmentInExpression);
                        case MYSELF:
                            EqualsTo myselfEqualsTo = new EqualsTo();
                            myselfEqualsTo.setLeftExpression(new Column(creatorFiled));
                            myselfEqualsTo.setRightExpression(new LongValue(StpUtil.getLoginIdAsInt()));
                            return new AndExpression(where, myselfEqualsTo);
                        case CUSTOM:
                            String permission = rolePermission.getPermission();
                            Set<String> departmentSet = new HashSet<>(Arrays.asList(permission.split(",")));
                            ItemsList customItemsList = new ExpressionList(departmentSet.stream().map(LongValue::new).collect(Collectors.toList()));
                            InExpression customInExpression = new InExpression(new Column(departmentFiled), customItemsList);
                            return new AndExpression(where, customInExpression);
                        default:
                            break;
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return where;
    }
}
